﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using Pub;
using System.Collections;

namespace LZQXT.Test
{
    public partial class FClsView : Form
    {

        String fileName = "";
        MethodInfo method2;
        Type typ2;

        public FClsView()
        {
            InitializeComponent();
        }

        // Checks a method for a signature match, and invokes it if there is one
        private static Object AttemptMethod(Type type, MethodInfo method, String name, String[] args)
        {
            // Name does not match?
            if (String.Compare(method.Name, name, false, CultureInfo.InvariantCulture) != 0)
            {
                throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Name Doesn't Match!");
            }

            // Wrong number of parameters?
            ParameterInfo[] param = method.GetParameters();

            //执行无参方法
            if (param.Length == 0 && args[0] == "")
            {
                Object instance = null;

                if (!method.IsStatic)
                {
                    instance = Activator.CreateInstance(type);
                }

                // ok, let's invoke this one!
                return method.Invoke(instance, null);
            }
            else
            {

                if (param.Length != args.Length)
                {
                    throw new CustomException(method.DeclaringType + "." + method.Name + ": Method Signatures Don't Match!");
                }

                // Ok, can we convert the strings to the right types?
                Object[] newArgs = new Object[args.Length];

                for (int index = 0; index < args.Length; index++)
                {
                    try
                    {
                        newArgs[index] = Convert.ChangeType(args[index], param[index].ParameterType, CultureInfo.InvariantCulture);
                    }
                    catch (Exception e)
                    {
                        throw new CustomException(method.DeclaringType + "." + method.Name + ": Argument Conversion Failed", e);
                    }
                }

                // We made it this far, lets see if we need an instance of this type
                Object instance = null;

                if (!method.IsStatic)
                {
                    instance = Activator.CreateInstance(type);
                }

                // ok, let's invoke this one!
                return method.Invoke(instance, newArgs);
            }
        }

        // Print usage
        private static void Usage()
        {
            Console.WriteLine("Usage:\n" + "   Invoke [Assembly] [Type] [Method] [Parameters...]");
        }

        //测试选中的方法
        private void btnExec_Click(object sender, EventArgs e)
        {
            String methodName = tboxMethod.Text;
            String sVal = tboxValue.Text;

            try
            {

                Object obj = null;

                try
                {
                    obj = AttemptMethod(typ2, method2, methodName, sVal.Split(','));
                }
                catch (CustomException e1)
                {
                    //MessageBox.Show(e1.ToString());
                    CDebug.Send(e1.ToString());
                }

                // If we make it this far without a throw, our job is done!
                tboxReturn.AppendText(obj.ToString() + "\n");

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.FileName.Length == 0)
                openFileDialog1.InitialDirectory = Application.StartupPath;

            openFileDialog1.Filter = "*.dll;*.exe|*.dll;*.exe";
            if (openFileDialog1.ShowDialog() == DialogResult.OK)
            {
                fileName = openFileDialog1.FileName;
                labFileName.Text = fileName;

                FileInfo finf = new FileInfo(fileName);
                tboxAssmebly.Text = finf.Name.Remove(finf.Name.Length - finf.Extension.Length);

                refTreeView();
            }
        }

        private void butCls_Click(object sender, EventArgs e)
        {
            tboxReturn.Clear();
        }

        private void chkBoxFullName_CheckedChanged(object sender, EventArgs e)
        {
            refTreeView();
        }

        private void FMain_Load(object sender, EventArgs e)
        {
            treeView1.Dock = DockStyle.Fill;
            groupBox2.Dock = DockStyle.Fill;

        }

        /// <summary>
        /// 获取类type1中的所有方法，填充node节点
        /// </summary>
        /// <param name="type1"></param>
        /// <param name="node"></param>
        private void getTypeInfo(Type type1, TreeNode2 node)
        {
            if (btnShowFullName.Checked)
            {
                node.Text = type1.FullName;
            }
            else
            {
                node.Text = type1.Name;
            }
            node.type1 = type1;
            node.i_type = 1;
            node.ImageIndex = 1;
            node.SelectedImageIndex = 1;

            /*
            MethodInfo[] methods = type1.GetMethods();

            // Try each method for a match
            StringBuilder failureExcuses = new StringBuilder();

            foreach (MethodInfo m in methods)
            {
                ParameterInfo[] parameters = m.GetParameters();

                String sparm = "";
                for (int i = 0; i < parameters.Length; i++)
                {
                    if (i != 0) sparm += ", ";
                    sparm += "[" + parameters[i].ParameterType.Name + "] " + parameters[i].Name;
                }

                TreeNode2 node2 = new TreeNode2();
                node2.Text = "[" + m.ReturnType.Name + "] " + m.Name + "(" + sparm + ")";
                node2.method1 = m;
                node2.i_type = 2;
                node.Nodes.Add(node2);
            }
            */

            MemberInfo[] member1 = type1.GetMembers();

            // Try each method for a match
            StringBuilder failureExcuses = new StringBuilder();

            foreach (MemberInfo m in member1)
            {

                TreeNode2 node2 = new TreeNode2();
                node2.Text = "[" + m.MemberType + "] " + m.Name;
                node2.ImageIndex = 2;
                node2.SelectedImageIndex = 2;
                //CDebug.Send(m.MemberType.ToString() + ", " + typeof(MethodInfo).Name);
                if (m.MemberType.ToString() == "Method")
                {
                    MethodInfo method1 = (MethodInfo)m;
                    ParameterInfo[] parameters = method1.GetParameters();

                    String sparm = "";
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        if (i != 0) sparm += ", ";
                        sparm += "" + parameters[i].ParameterType.Name + " " + parameters[i].Name;
                    }
                    node2.Text = "[" + m.MemberType + "] " + method1.ReturnType.Name + " " + m.Name + "(" + sparm + ")";
                    node2.i_type = 2;
                    node2.method1 = (MethodInfo)m;
                }

                if (m.MemberType.ToString() == "Field")
                {
                    FieldInfo field1 = (FieldInfo)m;

                    node2.Text = "[" + m.MemberType + "] " + field1.FieldType.Name + " " + m.Name;
                    node2.i_type = 3;
                    node2.ImageIndex = 3;
                    node2.SelectedImageIndex = 3;
                }

                node.Nodes.Add(node2);
            }
        }

        //显示类列表到treeview
        private void refTreeView()
        {
            treeView1.Nodes.Clear();

            try
            {
                Assembly SampleAssembly;
                SampleAssembly = Assembly.LoadFrom(fileName);

                Type[] types = SampleAssembly.GetTypes();

                foreach (Type type1 in types)
                {
                    TreeNode2 node = new TreeNode2();
                    getTypeInfo(type1, node);

                    treeView1.Nodes.Add(node);
                }

                //排序
                //treeView1.TreeViewNodeSorter = new NodeSorter();

            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            try
            {
                TreeNode2 node = (TreeNode2)treeView1.SelectedNode;
                if (node.i_type == 1)
                {
                    typ2 = node.type1;
                    if (node.Nodes.Count > 0)
                    {
                        TreeNode2 node2 = (TreeNode2)node.Nodes[0];
                        method2 = node2.method1;
                    }
                }
                else if (node.i_type == 2)
                {
                    TreeNode2 node2 = (TreeNode2)node.Parent;
                    typ2 = node2.type1;
                    method2 = node.method1;
                }

                propertyGrid1.SelectedObject = method2;

                tboxType.Text = typ2.Name;
                tboxMethod.Text = method2.Name;

                tboxValue.Clear();
                for (int i = 0; i < method2.GetParameters().Length; i++)
                {
                    //通过参数类型，初始化默认值
                    Type typ = method2.GetParameters()[i].ParameterType;
                    if (i > 0) tboxValue.Text += ",";

                    if (typ == typeof(string) || typ == typeof(object))
                    {
                        tboxValue.Text += method2.GetParameters()[i].Name;
                    }
                    else if (typ == typeof(int) || typ == typeof(double) || typ == typeof(float))
                    {
                        tboxValue.Text += "1";
                    }
                    else if (typ == typeof(bool))
                    {
                        tboxValue.Text += "true";
                    }
                    else
                    {
                        tboxValue.Text += "1";
                    }

                }
            }
            catch (System.Exception ex)
            {
                CDebug.SendError(ex.ToString());
            }
        }



        class CustomException : Exception
        {

            public CustomException(String m)
                : base(m)
            {
            }

            public CustomException(String m, Exception n)
                : base(m, n)
            {
            }

        }

    }

    public class TreeNode2 : TreeNode
    {

        public int i_paramCount = 0;
        public int i_type = 0;
        public MethodInfo method1;
        public Type type1;

    }


    public class NodeSorter : IComparer
    {
        // Compare the length of the strings, or the strings 
        // themselves, if they are the same length. 
        public int Compare(object x, object y)
        {
            TreeNode tx = x as TreeNode;
            TreeNode ty = y as TreeNode;

            // Compare the length of the strings, returning the difference. 
            if (tx.Text.Length != ty.Text.Length)
                return tx.Text.Length - ty.Text.Length;

            // If they are the same length, call Compare. 
            return string.Compare(ty.Text, tx.Text);
        }
    }


    public static class JTBOX
    {
        /// <summary>
        /// 注册插件
        /// </summary>
        /// <param name="node1"></param>
        /// <param name="list1"></param>
        /// <returns></returns>
        public static bool RegPlug(List<Form> list1, ImageList imgLst)
        {
            try
            {
                FClsView f1 = new FClsView();
                list1.Add(f1);

                imgLst.Images[list1.Count - 1] = f1.imageList2.Images[0];
            }
            catch (System.Exception ex)
            {
                //CDebug.SendError(ex.ToString());
                throw ex;
                //return false;
            }
            return true;
        }
    }

}